package ar.com.jendrix.common.persistence.entity.service;

import java.util.ArrayList;
import java.util.List;

import ar.com.jendrix.common.exception.ApplicationException;
import ar.com.jendrix.common.exception.SystemException;
import ar.com.jendrix.common.exception.ValidationException;
import ar.com.jendrix.common.persistence.entity.BaseEntity;
import ar.com.jendrix.common.persistence.entity.dto.BaseEntityDTO;
import ar.com.jendrix.common.persistence.manager.BaseEntityDAO;

public abstract class BaseEntityService<DTO extends BaseEntityDTO, BE extends BaseEntity> implements EntityService<DTO> {

	/**
	 * 
	 * @return
	 */
	protected abstract BaseEntityDAO<BE> getEntityDAO();

	/**
	 * 
	 * @param dto
	 * @return
	 * @throws SystemException
	 */
	public abstract BE mapToEntity(DTO dto) throws SystemException;

	/**
	 * 
	 * @param entity
	 * @return
	 */
	public abstract DTO mapToDTO(BE entity);

	/**
	 * 
	 * @param entityList
	 * @return
	 */
	protected final List<DTO> mapToDTO(List<BE> entityList) {
		List<DTO> dtoList = new ArrayList<DTO>();
		for (BE entity : entityList) {
			dtoList.add(mapToDTO(entity));
		}
		return dtoList;
	}

	/**
	 * 
	 * @param entityID
	 * @return
	 * @throws SystemException
	 */
	@Override
	public final DTO get(Long entityId) throws SystemException {
		DTO dto = null;
		try {
			BE entity = getEntityDAO().get(entityId);
			dto = mapToDTO(entity);
		} catch (Throwable t) {
			throw new SystemException(t);
		}
		return dto;
	}

	/**
	 * 
	 * @param entityId
	 * @return
	 * @throws SystemException
	 */
	@Override
	public final DTO getFull(Long entityId) throws SystemException {
		DTO dto = null;
		try {
			BE entity = getEntityDAO().getFull(entityId);
			dto = mapToDTO(entity);
		} catch (Throwable t) {
			throw new SystemException(t);
		}
		return dto;
	}

	/**
	 * 
	 * @return
	 * @throws SystemException
	 */
	@Override
	public final List<DTO> getList() throws SystemException {
		List<DTO> dtoList = null;
		try {
			List<BE> entityList = getEntityDAO().getList();
			dtoList = mapToDTO(entityList);
		} catch (Throwable t) {
			throw new SystemException(t);
		}
		return dtoList;
	}

	/**
	 * 
	 * @param entity
	 * @return
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	@Override
	public DTO save(DTO dto) throws ValidationException, ApplicationException, SystemException {
		DTO newDTO = null;
		try {

			validEntityData(dto);
			validEntityConstraint(dto);

			BE entity = mapToEntity(dto);
			BE newEntity = getEntityDAO().save(entity);
			newDTO = mapToDTO(newEntity);
		} catch (ValidationException v) {
			throw v;
		} catch (Throwable t) {
			throw new SystemException(t);
		}
		return newDTO;
	}

	protected abstract void validEntityData(DTO dto) throws ValidationException;

	protected void validEntityConstraint(DTO dto) throws ValidationException, SystemException {
	}

	/**
	 * 
	 * @param entityId
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	@Override
	public void delete(Long entityId) throws ApplicationException, SystemException {
		try {
			getEntityDAO().delete(entityId);

		} catch (Throwable t) {
			throw new SystemException(t);
		}
	}

	/**
	 * 
	 * @param entityId
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	@Override
	public void logicalDelete(Long entityId) throws ApplicationException, SystemException {
		try {
			getEntityDAO().logicalDelete(entityId);
		} catch (Throwable t) {
			throw new SystemException(t);
		}
	}
}